﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace CustomDataGridViewColumn
{
    public class RatingStarColumn : DataGridViewImageColumn
    {
        public RatingStarColumn()
        {
            this.CellTemplate = new RatingStarCell();
            this.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
            this.ValueType = typeof(int);
        }
    }

    public class RatingStarCell : DataGridViewImageCell
    {
        /// <summary>
        /// Khai báo giá trị kiểu int
        /// </summary>
        public RatingStarCell()
        {
            this.ValueType = typeof(int);
        }

        /// <summary>
        /// Lấy ra giá trị tại cell
        /// </summary>
        /// <returns>Convert int sang star images</returns>
        protected override object GetFormattedValue(object value, int rowIndex, ref DataGridViewCellStyle cellStyle, TypeConverter valueTypeConverter, TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context)
        {
                return starImages[(int)value];
        }

        /// <summary>
        /// Gán giá tri mặc định để tránh null
        /// </summary>
        public override object DefaultNewRowValue
        {
            get { return 3; }
        }

        /// <summary>
        /// Vẽ len datagridview RatingStar khớp với giá trị đã có
        /// </summary>
        protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
        {
            Image cellImage = (Image)formattedValue;
            int starNumber = GetStarFromMouse(cellBounds, this.DataGridView.PointToClient(Control.MousePosition));
            if (starNumber != -1)
                cellImage = starHotImages[starNumber];
            base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, cellImage, errorText, cellStyle, advancedBorderStyle, (paintParts & ~DataGridViewPaintParts.SelectionBackground));
        }

        /// <summary>
        /// Cập nhật lại giá trị tại cell khi người dùng bấm lên RatingStar
        /// </summary>
        /// <param name="e"></param>
        protected override void OnContentClick(DataGridViewCellEventArgs e)
        {
            base.OnContentClick(e);
            int starNumber = GetStarFromMouse(this.DataGridView.GetCellDisplayRectangle(this.DataGridView.CurrentCellAddress.X, this.DataGridView.CurrentCellAddress.Y, false), this.DataGridView.PointToClient(Control.MousePosition));

            if (starNumber != -1)
                this.Value = starNumber;
        }
        
        /// <summary>
        /// Vô hiệu hóa các tác động lên cell khi rê chuột trong cell hay di chuyển qua cell khác
        /// </summary>
        /// <param name="rowIndex"></param>
        #region
        protected override void OnMouseLeave(int rowIndex)
        {
            base.OnMouseLeave(rowIndex);
            this.DataGridView.InvalidateCell(this);
        }
        protected override void OnMouseMove(DataGridViewCellMouseEventArgs e)
        {
            base.OnMouseMove(e);
            this.DataGridView.InvalidateCell(this);
        }
        #endregion

        /// <summary>
        /// Các hàm private chạy tính toán và hiển thị
        /// </summary>
        #region
        static Image[] starImages;
        static Image[] starHotImages;
        const int IMAGEWIDTH = 67;
        
        /// <summary>
        /// Lấy giá trị RatingStar bàng vị trí chuột
        /// </summary>
        /// <param name="cellBounds">Biên giới của cell, ở đây sử dụng tọa độ X để tính</param>
        /// <param name="mouseLocation">Vị trí chuột hiện tại</param>
        /// <returns></returns>
        private int GetStarFromMouse(Rectangle cellBounds, Point mouseLocation)
        {
            if (cellBounds.Contains(mouseLocation))
            {

                int mouseXRelativeToCell = (mouseLocation.X - cellBounds.X);
                int imageXArea = (cellBounds.Width / 2) - (IMAGEWIDTH / 2);
                if (((mouseXRelativeToCell + 4) < imageXArea) || (mouseXRelativeToCell >= (imageXArea + IMAGEWIDTH)))
                    return -1;
                else
                {
                    int oo = (int)Math.Round((((float)(mouseXRelativeToCell - imageXArea + 5) / (float)IMAGEWIDTH) * 5f), MidpointRounding.AwayFromZero);
                    if (oo > 5 || oo < 0) System.Diagnostics.Debugger.Break();
                    return oo;
                }
            }
            else
                return -1;
        }
        
        /// <summary>
        /// Load các image của RatingStar
        /// </summary>
        #region
        static RatingStarCell()
        {
            starImages = new Image[6];
            starHotImages = new Image[6];
            for (int i = 0; i <= 5; i++)
            {
                starImages[i] = (Image)CuaHangDiaNhac.Properties.Resources.ResourceManager.GetObject("star" + i.ToString());
            }
            for (int i = 0; i <= 5; i++)
            {
                starHotImages[i] = (Image)CuaHangDiaNhac.Properties.Resources.ResourceManager.GetObject("starhot" + i.ToString());
            }
        }
        #endregion
    
        #endregion

    }
}
